package com.ywj.client;

import javax.websocket.*;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URI;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
//import org.slf4j.Logger;
//import org.slf4j.LoggerFactory;

import java.net.URL;
import java.sql.Time;
import java.util.Date;
import java.util.UUID;

//@Slf4j
@ClientEndpoint
public class WebSocketClientHeartBeat {
//    public static Logger logger = LoggerFactory.getLogger(WSHeartBeatRunnable.class);
    static Session session;
    static String wsUrl = "ws://localhost:8888";

//    public WebSocketClientHeartBeat(String url){
//        try{
//            WebSocketContainer container = ContainerProvider.getWebSocketContainer();
//            session = container.connectToServer(this, new URI(url));
//            session.getBasicRemote().sendText("简单做个测试");
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//    }

    public void sendHeartBeat() {
        try{
            session.getBasicRemote().sendText("heartbeat");
            System.out.println("发送心跳数据成功");
        } catch (Exception e) {
            e.printStackTrace();
        }
//        Time timeout = 10*1000;  //10s一次心跳
    }


    @OnOpen
    public void onOpen(Session session) {
//        System.out.println("Connected to endpoint: " + session.getBasicRemote());
        try {
            this.session=session;
            System.out.println("当前会话为:   " + session);
            String name = "Duke";
            System.out.println("Sending message to endpoint: " + name);
            session.getBasicRemote().sendText(name);  //向服务端发消息
        } catch (IOException ex) {
            ex.printStackTrace();
        }
        //连接成功后onOpen执行的逻辑——心跳监测；接收消息onMessage后进行心跳重置；
        //连接关闭时onMessage 关闭心跳机制

        //每隔10s发送一次心跳消息
//        while(true){
            //发送心跳消息
//           session.getBasicRemote().sendText("");
           //等待服务器响应，超时时间为10秒钟
//           session.setMaxIdleTimeout(10000);

           //暂停10秒种
//            Thread.sleep(10000);
//        }


    }

    @OnMessage     //服务端发来消息后的处理方法
    public void processMessage(String message) {
        //对方发来的消息，进行处理
        System.out.println("Received message in client: " + message);
    }

    @OnError
    public void processError(Throwable t) {
        t.printStackTrace();
    }

    @OnClose
    public void onClose(){
        System.out.println("与服务端端开连接");
        reConnect();
        System.out.println("连接断开，重连成功，session为： " + session);
    }


    public static void main(String[] args) {
        System.out.println("自己写的WebSocket客户端");
//        WebSocketClientHeartBeat wscHB = new WebSocketClientHeartBeat(wsUrl);
//        wscHB.sendHeartBeat();
//        new Thread(new KeepHeartThread()).start();
        new Thread(new WSHeartBeatRunnable()).start();
        new Thread(new KeepHeartThread()).start();
        System.out.println("开心，希望能成功");
    }

    public static synchronized void reConnect(){
        try {
            //判断是否是重新连接状态
            if(session == null){
                WebSocketContainer container = ContainerProvider.getWebSocketContainer();
//            WebSocketContainer container = ClientManager.createClient();
                session = container.connectToServer(WebSocketClientHeartBeat.class, new URI(wsUrl));
                System.out.println("reConnect重连成功， session为： " + session);
            }
            //短线重连后，需重新启动心跳线程
            new Thread(new WSHeartBeatRunnable()).start();
        } catch (Exception e) {
//            logger.info("重连失败");
            System.out.println("重连失败");
        }
    }

    //发送心跳包，10s一次
    public static class KeepHeartThread implements Runnable{
        //@SneakyThrows注解是由lombok为我们封装的，它可以为我们的代码生成一个try...catch块，并把异常向上抛出来，
        //而你之前的ex.getStackTrace()是没有这种能力的，有时，我们从底层抛出的异常需要被上层统一收集，
        //而又不想在底层new出一大堆业务相关的异常实例，这时使用@SneakyThrows可以简化我们的代码。
        @SneakyThrows
        @Override
        public void run() {
            while(true){
                if(session == null){
                    try {
                        System.out.println("session is null, try to connect 第三方，URL =" + wsUrl);
//                        logger.info("session is null, try to connect 第三方，URL = {}", wsUrl);
//                            WebSocketContainer container = ClientManager.createClient();
//                            WebSocketContainer container = ContainerProvider.getWebSocketContainer();
//                            session = container.connectToServer(MyWebSocketClient.class, new URI(wsUrl));
                        reConnect();
//                        logger.info("connect websocket server successfully, URL = {}, sessionId = {}", wsUrl, session.getId());
                        System.out.println("connect websocket server successfully, URL = {" + wsUrl + "}, sessionId =  " + session.getId());
                    } catch (Exception e) {
//                            logger.info("connect to websocket server error, {}", e);
//                        logger.info("WebSocket连接服务端异常，{}", e);
//                        System.out.println("WebSocket连接服务端异常，" + e);
                        System.out.println("WebSocket连接服务端异常，请检查服务端是否开启" );
                        Thread.sleep(30000);
//                        continue;

                    }
                }
                if(session != null){
                    System.out.println("当前WebSocketClientHeartBeat的session为： " + WebSocketClientHeartBeat.session.getId());
                    try{
                        JSONObject responseObject = sendPost("http://10.169.122.110/gkApi/searchMember", addJSONObject());
                        System.out.println(new Date() + ",   sendPost方法响应体：simTest time  ");
                        Thread.sleep(100000);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }


            }

        }
    }


    /**
     * 向指定URL发送POST方法的请求
     *
     * @param url  发送请求的URL
     * @param body 请求参数，为json格式
     * @return 所代表远程资源的响应结果
     */
    public static JSONObject sendPost(String url, JSONObject body)  {
        InputStream inputStream = null;
        HttpURLConnection httpURLConnection = null;
        StringBuilder result = new StringBuilder();
        try {
            URL realUrl = new URL(url);
            //打开和URL之间的连接
            httpURLConnection = (HttpURLConnection) realUrl.openConnection();
            // 请求方式
            httpURLConnection.setRequestMethod("POST");
            //设置超时时间
            httpURLConnection.setConnectTimeout(300000);
            httpURLConnection.setReadTimeout(300000);
            //post请求。发送POST请求必须设置如下两行
            //设置是否向 HttpUrlConnection 输出，对于post请求，参数要放在 http 正文内，因此需要设为true，默认为false。
            httpURLConnection.setDoOutput(true);
            //设置是否从 HttpUrlConnection读入，默认为true
            httpURLConnection.setDoInput(true);


            // 设置是否使用缓存
            httpURLConnection.setUseCaches(false);
            // 设置此 HttpURLConnection 实例是否应该自动执行 HTTP 重定向
            httpURLConnection.setInstanceFollowRedirects(true);
            // 设置使用标准编码格式编码参数的名-值对
            httpURLConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
            httpURLConnection.setRequestProperty("Content-Type", "application/json");

            // 添加 HTTP HEAD 中的一些参数。

            //建立实际的连接
            httpURLConnection.connect();

            //发送数据,获取HttpURLCOnnection对象对应的输出流
            OutputStream outputStream = httpURLConnection.getOutputStream();
            //经测试 outputStream为请求的body  "{"username":"admin", "imsi":"460007210437022",...,"pageSize":10 }"
            outputStream.write(JSON.toJSONString(body).getBytes());

            outputStream.flush();
            outputStream.close();
            //请求数据。使用inputStream来获取URL的响应


            //获取返回码
            int code = httpURLConnection.getResponseCode();
            if(code >= 400){  //415
                inputStream = httpURLConnection.getErrorStream();
            } else {
                inputStream = httpURLConnection.getInputStream();
            }
            //在此处出现问题，经过了catch、finally块
//            inputStream = httpURLConnection.getInputStream();

            byte[] bytes = new byte[1024 * 1024];
            int len;
            while ((len = inputStream.read(bytes)) != -1) {
                result.append(new String(bytes, 0, len));
//                System.out.println(new String(bytes, 0, len));
            }
            if(inputStream != null){
                inputStream.close();
            }
//            return JSON.parseObject(result.toString());
        } catch (Exception e){
//            logger.info("服务端发来的POST请求 处理失败");
            System.out.println("服务端发来的POST请求 处理失败");
        }
        finally {
            if(httpURLConnection != null)
                httpURLConnection.disconnect();
        }
        return JSON.parseObject(result.toString());
    }


    public static JSONObject addJSONObject(){
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("username","admin");
        jsonObject.put("password","argus@1234");
        jsonObject.put("id","45");
        jsonObject.put("groupId", 27);
        jsonObject.put("name", "swtest1");
        jsonObject.put("imsi", "460007210437022");
        jsonObject.put("mobile", "13312345678");
        jsonObject.put("position", "xs");
        jsonObject.put("pageIndex", 1);
        jsonObject.put("pageSize", 10);
        return jsonObject;
    }

}


